经典算法之《八皇后》
八皇后问题,是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:
在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
其实这个算法挺简单,但是久仰八皇后的大名一直没下手,其实就是一个dfs+回溯,记得给点染色和清除染色就ok,一共92种摆法,
自我感觉自己的代码还是挺简单的,而且觉得算法比百度百科里面还是要好那么一些,于是就果断贴上来了;temp[]数组用来存放每一种摆
法的状态,为8位的整数,每一位代表每一行所放置的列的位置。
下面来分析一下算法吧:我们对每一个合适的点进行dfs,由于每一行只能放一个棋子,所以一旦有了合适的位置放置棋子就往下一行
摆放,同时把这个点标记为已经放棋子,这样在下面的dfs中就可以来判断存放下一颗棋子是否符合标准,如果符合则继续下一行,最后当row==8
时,回溯,同时消除上一个放置点的标记。这样的遍历便不重复。ps:在判断的时候可以适当优化,不过这个算法也已经很快
1 //==================================================================== 2 //Name :经典问题--八皇后 3 //Author :hxf 4 //copyright :http://www.cnblogs.com/Free-rein/ 5 //Description: 6 //Data :2012.8.19 7 //======================================================================== 8 #include<iostream> 9 #include<algorithm> 10 #include<stdio.h> 11 #include<math.h> 12 #include<string> 13 #include<cstring> 14 #include<vector> 15 #include<stack> 16 #include<queue> 17 #define MAXN 100050 18 #define inf 10100 19 using namespace std; 20 int map[10][10]; 21 int ans=0; 22 int temp[100];//存放结果状态 23 void dfs(int row) 24 { 25 for(int j=1;j<=8;j++) 26 { 27 int s=0;//在下面的判断里若不符合要求则标记为1 28 for(int i=1;i<row;i++) 29 { 30 if(map[i][j]==1) 31 s=1; 32 for(int k=1;k<=8;k++) 33 if(((row-i==j-k)||(row-i==k-j))&&map[i][k]==1) 34 { 35 s=1; 36 break; 37 } 38 } 39 if(s==0&&row<8)//第row行第j列符合存放要求 40 { 41 map[row][j]=1;//标记颜色 42 dfs(row+1);//dfs下一行 43 map[row][j]=0;//dfs完毕,消除染色 44 } 45 if(s==0&&row==8) 46 { 47 int state=0; 48 for(int i=1;i<8;i++) 49 { 50 for(int k=1;k<=8;k++) 51 { 52 if(map[i][k]==1) 53 state=state+k; 54 } 55 state=state*10; 56 } 57 state=state+j; 58 ans++;//计数器+1 59 temp[ans]=state; 60 break; 61 } 62 } 63 } 64 int main() 65 { 66 memset(map,0,sizeof(map)); 67 for(int j=1;j<=8;j++) 68 { 69 map[1][j]=1; 70 dfs(2); 71 map[1][j]=0; 72 } 73 printf("%d\n",ans); 74 while(1) 75 { 76 int n; 77 scanf("%d",&n);//输入n 78 printf("%d\n",temp[n]);//输出第n种状态 79 } 80 return 0; 81 }
是不是代码完了就没事了呢?处在学习阶段果断不能这样(→_→) ...我们想想还有木有别的方法,建图的话那就差不多了,当然我们也可以不用染色,而用hash,在这里
一共也不过8^8种状态量,于是构建一个hash表来存放每一种状态,如果这种状态已经处理过了则可以直接跳过,应该也是可以得到答案的...